#include "../../tdp2/tdp2_vector.hpp"
#include "../../tdp2/tdp2_linkedlist.hpp"
#include "../../tdp2/tdp2_maincontext.hpp"
#include "../../tdp2/tdp2_visualresources.hpp"
#include "../../../rdx/src/rdx/rdx_objectmanagement.hpp"

#define R2_MAX_SHADERS	500

extern "C"
{
#include "../renderer/tr_local.h"
}
#include "tr_r2.h"

using namespace TDP;
using namespace TDP::Containers;
using namespace RDX;
using namespace RDX::ObjectManagement;

typedef struct
{
	char name[MAX_PATH];
	CRef<void> material;
} r2_namedshader_t;

static r2_namedshader_t r_shaders[R2_MAX_SHADERS];
static LargeUInt r_numShaders = 0;

void *R2_ShaderFromHandle( qhandle_t h )
{
	if(h > r_numShaders || h <= 0)
		return NULL;
	return static_cast<void *>(r_shaders[h-1].material);
}

qhandle_t	R2_RegisterShader( const TDP::PanicHandler *ph, const char *name )
{
	if(strlen(name) >= MAX_PATH)
		return 0;

	for(LargeUInt i=0;i<r_numShaders;i++)
	{
		if(!strcmp(r_shaders[i].name, name))
			return static_cast<qhandle_t>(i+1);
	}

	{
		OperationContext ctx(r_mctx->ObjectManager());
		RDX_TRY(&ctx)
		{
			IObjectManager *objm = r_mctx->ObjectManager();
			CRef<const String> symbolName;
			CRef<Type> materialType;
			CRef<Resources::Material> material;

			RDX_PROTECT_ASSIGN(&ctx, symbolName, objm->CreateStringASCII(&ctx, name));
			RDX_PROTECT_ASSIGN(&ctx, material, r_mctx->LookupSymbol(&ctx, symbolName).ReinterpretCast<Resources::Material>());

			if(material == NULL)
				return 0;

			RDX_PROTECT_ASSIGN(&ctx, symbolName, objm->CreateStringASCII(&ctx, "TDP.Resources.Material"));
			RDX_PROTECT_ASSIGN(&ctx, materialType, r_mctx->LookupSymbol(&ctx, symbolName).ReinterpretCast<Type>());

			if(!objm->ObjectCompatible(material, materialType))
				return 0;

			LargeUInt oldCount = r_numShaders++;
			r2_namedshader_t *shaderRef = r_shaders + oldCount;

			shaderRef->material = material;
			strcpy(shaderRef->name, name);

			return static_cast<qhandle_t>(oldCount + 1);
		}
		RDX_CATCH(&ctx)
		{
			R2_FatalError(&ctx);
		}
		RDX_ENDTRY
	}

	return 0;
}

void		R2_ShutdownShaders()
{
	while(r_numShaders > 0)
	{
		r_numShaders--;
		r_shaders[r_numShaders].material = NULL;
	}
}
